package shapewar.engine.calc;

import java.util.Iterator;

import shapewar.conf.Conf;
import shapewar.engine.intefac.IHittable;
import shapewar.engine.intefac.IRegisterable;
import shapewar.engine.intefac.ITank;
import shapewar.engine.model.Wall;
import shapewar.engine.presenter.Presenter;

public class Calcer extends Calc {
	private Presenter pst;
	public Calcer(Presenter pst){
		this.pst = pst;
	}
	
	
	public boolean limitPos(Pos newPos,IHittable who) {
		float tmp_x = newPos.x;
		float tmp_y = newPos.y;
		boolean bo = false;
		//Edge limit
		if(tmp_x<0){
			tmp_x = 0;
			bo = true;
		}
		if(tmp_x>Conf.map_width){
			tmp_x = Conf.map_width;
			bo = true;
		}
		if(tmp_y<0){
			tmp_y = 0;
			bo = true;
		}
		if(tmp_y>Conf.map_height){
			tmp_y = Conf.map_height;
			bo = true;
		}
		newPos.x = tmp_x;
		newPos.y = tmp_y;
		if(bo)return true;
		//Wall limit
		/*
		 * rem for:V1.0.2
		 */
//		Iterator<IRegisterable> it = pst.ect.tr_wall.iterator();
//		while(it.hasNext()){
//			IHittable wall = (IHittable) it.next();
//			float v[][] = wall.getVertices();
//			if(hitTest(newPos, wall.getPos(), v, wall.getHitableDistance())){
//				newPos.x = who.getPos().x;
//				newPos.y = who.getPos().y;
//				return true;
//			}
//		}
		return false;
	}
	
	/*
	 * add for V1.0.2
	 */
	public IHittable isInWall(Pos newPos,IHittable who){
		Iterator<IRegisterable> it = pst.ect.tr_wall.iterator();
		while(it.hasNext()){
			IHittable wall = (IHittable) it.next();
			float v[][] = wall.getVertices();
			if(hitTest(newPos, wall.getPos(), v, wall.getHitableDistance())){
				return wall;
			}
		}
		return null;
	}
	
	public IHittable hitTanks(IHittable blt){
		Iterator<IRegisterable> tanks = pst.ect.tr_tank.iterator();
		while(tanks.hasNext()){
			IHittable tank = (IHittable) tanks.next();
			if(blt.getFather()==tank)continue;
			if(hitTest(blt.getPos(),tank.getPos(),tank.getVertices(), tank.getHitableDistance() + blt.getHitableDistance())){
				return tank;
			}
		}
		return null;
	}
	
	public IHittable hitProtectors(IHittable blt) {
		Iterator<IRegisterable> tanks = pst.ect.tr_tank.iterator();
		while(tanks.hasNext()){
			IHittable tank = (IHittable) tanks.next();
			if(blt.getFather()==tank)continue;
			if(((ITank)tank).getProtector().hitTest(blt)){
				return ((ITank)tank).getProtector();
			}
		}
		return null;
	}
	
	public boolean move(Pos pos,Pos target,float speed) {
		if(calcDistance(pos, target)<speed)return false;
		float angle = calcAngle(pos, target);
		pos.x += speed * Math.cos(angle * Math.PI / 180);
		pos.y += speed * -Math.sin(angle * Math.PI / 180);
		return true;
	}
	
	public boolean canFire(Pos pos_a,Pos pos_c,float angle,float can_fire_dis,Wall wall) {
		Iterator<IRegisterable> hitable = pst.ect.tr_tank.iterator();
		while(hitable.hasNext()){
			IHittable tmp = (IHittable) hitable.next();
			Pos pos_b = tmp.getPos();
			if(calcDistance(pos_a, pos_b)>can_fire_dis)continue;
//			/*
//			 * add for 1.0.4 
//			 * can not fire while tank is hide
//			 */
//			if(tmp instanceof ITank){
//				if((((ITank)tmp).getInstance()).wall!=wall)
//					continue;
//			}
			if(canFire(pos_a, pos_b, pos_c, angle))return true;
		}
		return false;
	}

	public ITank getTank(int _id) {
		Iterator<IRegisterable> tanks = pst.ect.tr_tank.iterator();
		while(tanks.hasNext()){
			ITank tk = (ITank) tanks.next();
			if(tanks.next().getId() == _id){
				return tk;
			}
		}
		return null;
	}
	
	public ITank getNeighbouringTankBy(ITank tank){
		Iterator<IRegisterable> tanks = pst.ect.tr_tank.iterator();
		while(tanks.hasNext()){
			ITank tk = (ITank) tanks.next();
			if(calcDistance(tank.getInstance().getPos(), tk.getInstance().getPos())<Conf.visible_area_radium*1.2){
				return tk;
			}
		}
		return null;
	}

}
